#include <GameEngine/Graphics/Camera/camera.h>

#ifdef WIN32
#include <windows.h>
#endif
#include <GL/glu.h>


#ifdef GAMEENGINE_NAMESPACES
namespace GameEngine {
#endif


//! Default constructor
Camera::Camera() : eye_(0,1,0), target_(0,0,0), up_(0,0,1), zoom_(0.0f) {}

//! Copy constructor
/*!
 @param rhs The camera to copy
 */
Camera::Camera(const Camera& rhs) : eye_(rhs.eye_), target_(rhs.target_), up_(rhs.up_) {}

//! Assignment operator
/*!
 @param rhs The camera to copy
 @return A reference to this camera
 */
Camera& Camera::operator=(const Camera& rhs) {
	if ( &rhs != this ) {
		eye_ = rhs.eye_;
		target_ = rhs.target_;
		up_ = rhs.up_;
	}
	return *this;
}

//! Destructor
Camera::~Camera() {}

//! Accessor to the location of the observer (read only)
/*!
 @return A constant reference to the location of the observer
 */
const Point3d<float>& Camera::eye() const {
	return eye_;
}

//! Accessor to the location of the observer (read-write)
/*!
 @return A reference to the location of the observer
 */
Point3d<float>& Camera::eye() {
	return eye_;
}

//! Accessor to the location of the target reference point (read only)
/*!
 @return A constant reference to the location of the target reference point
 */
const Point3d<float>& Camera::target() const {
	return target_;
}

//! Accessor to the location of the target reference point (read-write)
/*!
 @return A reference to the location of the target reference point
 */
Point3d<float>& Camera::target() {
	return target_;
}

//! Accessor to the "up" orientation relatively to the observer (read only)
/*!
 @return A constant reference to the "up" orientation relatively to the observer
 */
const Vector3d<float>& Camera::up() const {
	return up_;
}

//! Accessor to the "up" orientation relatively to the observer (read-write)
/*!
 @return A reference to the "up" orientation relatively to the observer
 */
Vector3d<float>& Camera::up() {
	return up_;
}

//! Accessor to the zoom factor (read only)
/*!
 @return The zoom factor
 */
float Camera::zoom() const {
	return zoom_;
}

//! Accessor to the zoom factor (read-write)
/*!
 @return A reference to the zoom factor
 */
float& Camera::zoom() {
	return zoom_;
}

//! Apply the camera transformations
void Camera::apply_camera() const {
	// Look at target
	gluLookAt(
		(1.0-zoom_)*eye_.x() + zoom_*target_.x(), (1.0-zoom_)*eye_.y() + zoom_*target_.y(), (1.0-zoom_)*eye_.z() + zoom_*target_.z(),
		target_.x(),                              target_.y(),                              target_.z(),
		up_.x(),                                  up_.y(),                                  up_.z()
	);
}


#ifdef GAMEENGINE_NAMESPACES
} // namespace GameEngine
#endif
